﻿using GameDevClicker.Data;
using System.Collections.Generic;

/// <summary>
/// Base resource used in the game, allowing the core logic to work.
/// </summary>
public class Resource {
    private static List<Resource> _resources = new List<Resource>();
    
    public int Id { get; private set; }
    public string Name { get; private set; }
    public int Value { get; private set; }
    public int Modifier { get; private set; }

    /// <summary>
    /// Create a new resource.
    /// </summary>
    /// <param name="name">The name of the resource.</param>
    /// <param name="baseAmount">The amount the resource starts with.</param>
    /// <param name="baseModifier">The base modifier (in percentage) the resource starts with.</param>
    public Resource(ResourceType type, int baseAmount = 0, int baseModifier = 100) {
        Name = type.ToString();
        Id = (int)type;
        Value = baseAmount;
        Modifier = baseModifier;

        _resources.Add(this);
    }

    /// <summary>
    /// Remove the resource from the resources list when destroyed.
    /// </summary>
    ~Resource() {
        _resources.Remove(this);
    }

    /// <summary>
    /// Add an amount to the resource's value.
    /// </summary>
    /// <param name="amount">The amount to add to the resource (unmodified).</param>
    /// <param name="useModifier">Use the resource's modifier or not.></param>
    /// <returns>Returns the value of the resource after addition.</returns>
    public int Add(int amount, bool useModifier = true) {
        Value += (useModifier ? Modify(amount) : amount);
        return Value;
    }

    /// <summary>
    /// Check to remove a given amount from the resource's value. If this works, remove the amount.
    /// </summary>
    /// <param name="amount">The amount to remove from the resource.</param>
    /// <returns>Returns if the removing failed or not.</returns>
    public int Remove(int amount, bool useModifier = true) {
        Value -= (useModifier ? Modify(amount) : amount);
        return Value;
    }

    /// <summary>
    /// Add a percentage of the current value to the resource.
    /// </summary>
    /// <param name="percentage">The percentage to add to the resource.</param>
    /// <returns>Returns the value of the resource after addition.</returns>
    public int AddPercentage(int percentage) {
        float baseVal = (float)(Value) / 100f;
        float addition = baseVal * percentage;
        Value += (int)(addition);

        return Value;
    }

    /// <summary>
    /// Add a percentage to the modifier.
    /// </summary>
    /// <param name="percentage">The amount to add.</param>
    /// <returns>Returns the new modifier for this resource.</returns>
    public int AddModifier(int percentage) {
        Modifier += percentage;
        return Modifier;
    }

    /// <summary>
    /// Convert an int to use the current modifier.
    /// </summary>
    private int Modify(int amount) {
        float baseVal = (float)(amount) / 100f;
        float addition = baseVal * Modifier;
        amount += (int)(addition);
        return amount;
    }

    /// <summary>
    /// Find a resource based on its ResourceType.
    /// </summary>
    public static Resource Find(ResourceType type) {
        return _resources.Find(r => r.Id == (int)type);
    }

    /// <summary>
    /// Find a resource based on its name.
    /// </summary>
    public static Resource Find(int id) {
        return _resources.Find(r => r.Id == id);
    }

    /// <summary>
    /// Find a resource based on its ID.
    /// </summary>
    public static Resource Find(string name) {
        return _resources.Find(r => r.Name.Equals(name, System.StringComparison.OrdinalIgnoreCase));
    }
}